package com.xlh.support.quiz.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Lists;
import com.xlh.dao.user.ext.UserMapperExt;
import com.xlh.dto.quiz.EssayQuestionStaticsDTO;
import com.xlh.dto.quiz.TrueOrFalseQuestionStaticsDTO;
import com.xlh.dto.quiz.UserQuizStatusDTO;
import com.xlh.dto.user.ClassCourseDTO;
import com.xlh.dto.user.UserInfoDTO;
import com.xlh.enums.course.ChapterEnum;
import com.xlh.enums.user.UserStatusEnum;
import com.xlh.exception.common.GlobalException;
import com.xlh.pojo.course.Chapter;
import com.xlh.service.course.ChapterService;
import com.xlh.service.user.ClassService;
import com.xlh.service.user.UserService;
import com.xlh.support.quiz.constant.QuizPerformanceEnum;
import com.xlh.support.quiz.dao.helper.QuizAnswerMapperHelper;
import com.xlh.support.quiz.dao.helper.QuizMapperHelper;
import com.xlh.support.quiz.domain.Quiz;
import com.xlh.support.quiz.domain.QuizAnswer;
import com.xlh.support.quiz.po.QuizStatisticsQueryPO;
import com.xlh.support.quiz.service.QuizStatisticService;
import com.xlh.support.quiz.vo.QuizStatisticVO;
import com.xlh.util.ExcelsUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author cheer
 */
@Service
public class QuizStatisticServiceImpl implements QuizStatisticService {

    @Autowired
    private ClassService classService;

    @Autowired
    private UserService userService;

    @Autowired
    private ChapterService chapterService;

    @Autowired
    private UserMapperExt userMapperExt;

    @Autowired
    private QuizMapperHelper quizMapperHelper;

    @Autowired
    private QuizAnswerMapperHelper quizAnswerMapperHelper;

    @Override
    public List<QuizStatisticVO> listQuizStatistic(Long courseId, QuizStatisticsQueryPO quizStatisticsQueryPO) {
        List<ClassCourseDTO> classCourseDTOS = classService.listClassCourse(null, quizStatisticsQueryPO.getStatus(),
                null, null, quizStatisticsQueryPO.getClassIdList());
        if (CollectionUtils.isEmpty(classCourseDTOS)) {
            throw new GlobalException("班级不存在");
        }

        Map<Long, ClassCourseDTO> classMap = new HashMap<>();
        Set<Long> classIdSet = new HashSet<>();
        for (ClassCourseDTO classCourseDTO : classCourseDTOS) {
            classMap.put(classCourseDTO.getId(), classCourseDTO);
            classIdSet.add(classCourseDTO.getId());
        }

        List<UserInfoDTO> userList = userService.queryClassUser(quizStatisticsQueryPO.getUserInfo(),
                new ArrayList<>(classIdSet), Lists.newArrayList(UserStatusEnum.NOT_DELETE.getCode()), false);
        List<UserInfoDTO> userInfoDTOS = userMapperExt.listClassUserDelete(quizStatisticsQueryPO.getUserInfo(),
                null, new ArrayList<>(classIdSet));
        userList.addAll(userInfoDTOS);

        List<QuizStatisticVO> quizStatisticVOs = Lists.newArrayList();
        List<QuizAnswer> answers = findAnswerByUser(courseId, userList);
        Map<Long, List<QuizAnswer>> answerMap = aggByUserId(answers);

        for (UserInfoDTO user : userList) {
            QuizStatisticVO quizStatisticVO = QuizStatisticVO.builder()
                    .userId(user.getId())
                    .username(user.getName())
                    .userNumber(user.getUserNumber())
                    .className(classMap.get(user.getClassId()).getName())
                    .grade(classMap.get(user.getClassId()).getGrade())
                    .build();
            computePerformance(quizStatisticVO, answerMap.get(user.getId()));
            quizStatisticVOs.add(quizStatisticVO);
        }

        return quizStatisticVOs;
    }

    @Override
    public void downloadQuizStatistic(Long courseId, QuizStatisticsQueryPO quizStatisticsQueryPO) {
        List<QuizStatisticVO> quizStatisticVOs = listQuizStatistic(courseId, quizStatisticsQueryPO);

        List<Map<String, Object>> excelList = new ArrayList<>();
        Map<String, Object> header = new HashMap<>();
        header.put("sheetName", "随堂提问统计");
        excelList.add(header);

        for (QuizStatisticVO quizStatisticVO : quizStatisticVOs) {
            Map<String, Object> line = new HashMap<>();
            line.put("username", quizStatisticVO.getUsername());
            line.put("userNumber", quizStatisticVO.getUserNumber());
            line.put("className", quizStatisticVO.getClassName());
            line.put("grade", quizStatisticVO.getGrade());
            line.put("saq", quizStatisticVO.getSaqPerformance());
            line.put("judgement", quizStatisticVO.getJudgementPerformance());
            excelList.add(line);
        }

        String[] columnNames = {"姓名", "学号", "班级", "年级", "简答题", "判断题"};
        String[] keys = {"username", "userNumber", "className", "grade", "saq", "judgement"};
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        ExcelsUtil.ExcelSingleOutputStream(excelList, keys, columnNames, "quiz", request, response);
    }

    private List<QuizAnswer> findAnswerByUser(Long courseId, List<UserInfoDTO> userInfoDTOs) {
        if (CollectionUtils.isEmpty(userInfoDTOs)) {
            return new ArrayList<>();
        }
        List<Long> userIds = userInfoDTOs.stream().map(UserInfoDTO::getId).collect(Collectors.toList());

        List<Chapter> chapterList = chapterService.getChapter(courseId, ChapterEnum.CHAPTER);
        if (CollectionUtils.isEmpty(chapterList)) {
            return new ArrayList<>();
        }
        List<Long> chapterIds = chapterList.stream().map(Chapter::getId).collect(Collectors.toList());

        List<Quiz> quizzes = quizMapperHelper.listQuizByChapterIds(chapterIds);
        if (CollectionUtils.isEmpty(quizzes)) {
            return new ArrayList<>();
        }

        List<Long> quizIds = quizzes.stream().map(Quiz::getId).collect(Collectors.toList());
        return quizAnswerMapperHelper.listByQuizIdsAndUserIds(quizIds, userIds);
    }

    private Map<Long, List<QuizAnswer>> aggByUserId(List<QuizAnswer> quizAnswers) {
        Map<Long, List<QuizAnswer>> answerMap = new HashMap<>();
        for (QuizAnswer answer : quizAnswers) {
            if (answerMap.get(answer.getUserId()) == null) {
                List<QuizAnswer> answers = Lists.newArrayList(answer);
                answerMap.put(answer.getUserId(), answers);
            } else {
                answerMap.get(answer.getUserId()).add(answer);
            }
        }
        return answerMap;
    }

    private void computePerformance(QuizStatisticVO quizStatisticVO, List<QuizAnswer> answers) {
        int excellent = 0;
        int good = 0;
        int poor = 0;
        int correct = 0;
        int incorrect = 0;
        if (CollectionUtils.isNotEmpty(answers)) {
            for (QuizAnswer answer : answers) {
                QuizPerformanceEnum quizPerformanceEnum = QuizPerformanceEnum.forCode(answer.getPerformance());
                if (quizPerformanceEnum != null) {
                    switch (quizPerformanceEnum) {
                        case CORRECT:
                            correct++;
                            break;
                        case INCORRECT:
                            incorrect++;
                            break;
                        case EXCELLENT:
                            excellent++;
                            break;
                        case GOOD:
                            good++;
                            break;
                        case POOR:
                            poor++;
                            break;
                        default:
                    }
                }
            }
        }
        quizStatisticVO.setJudgementPerformance(String.format("%s 对  %s 错", correct, incorrect));
        quizStatisticVO.setSaqPerformance(String.format("%s 优  %s 良  %s 差", excellent, good, poor));
    }

    @Override
    public EssayQuestionStaticsDTO essayQuestionStatistic(Long chapterId, Long defaultClassId) {

        // 获取当前班级ID和课程ID下的所有学生
        List<Long> userIds = userService.getClassUser(defaultClassId);
        // 查询状态为未删除的学生
        if(CollectionUtil.isNotEmpty(userIds)){
            userIds = userMapperExt.findExistUser(userIds);
        }
        if(CollectionUtil.isEmpty(userIds)){
            return new EssayQuestionStaticsDTO(0L,0L,0L);
        }
        EssayQuestionStaticsDTO essayQuestionStaticsDTO = quizAnswerMapperHelper.essayQuestionStatistic(chapterId, userIds);
        return essayQuestionStaticsDTO;
    }

    @Override
    public TrueOrFalseQuestionStaticsDTO trueOrFalseQuestionsStatistic(Long defaultClassId, Long chapterId) {

        // 获取当前班级ID和课程ID下的所有学生
        List<Long> userIds = userService.getClassUser(defaultClassId);
        // 查询状态为未删除的学生
        if(CollectionUtil.isNotEmpty(userIds)){
            userIds = userMapperExt.findExistUser(userIds);
        }
        if(CollectionUtil.isEmpty(userIds)){
            return new TrueOrFalseQuestionStaticsDTO(0L,0L);
        }

        return quizAnswerMapperHelper.trueOrFalseQuestionsStatistic(chapterId, userIds);
    }


    @Override
    public List<UserQuizStatusDTO> findQuizStatisticByUserIds(List<Long> chapterIds, List<Long> userIds) {

        List<UserQuizStatusDTO> list = quizAnswerMapperHelper.findQuizStatisticByUserIds( chapterIds, userIds);

        return list;
    }


}
